﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "GnufExplorerBlockManager.h"
#include "GnufFamilyTreeNodeUtil.h"
#include "GnufModelViewBoard.h"
#include "GnufModelViewConfiguration.h"
#include "CmdAvailibilityUtils.h"
#include "CommandParameters.h"
#include "ComponentEditorCommandIds.h"
#include "ComponentEditorUiDocUtils.h"
#include "FamilyCmdAvailibilityUtils.h"
#include "GbmpBuiltInCategoryUniIdentities_private.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "GmCommunicationProtocolUtils.h"
#include "GnufAppearanceSetting.h"
#include "GnufDragMove.h"
#include "GnufDropdownMenu.h"
#include "GnufInfo.h"
#include "GnufMainWindow.h"
#include "GnufTree.h"
#include "IActionManager.h"
#include "IApplicationWindow.h"
#include "ICommandManager.h"
#include "IDrawingLayout.h"
#include "IDrawingLayoutManager.h"
#include "IDrawingViewport.h"
#include "IDrawingViewportEvent.h"
#include "IDrawingViewportEventArgs.h"
#include "IElement.h"
#include "IElementBasicInformation.h"
#include "IElementsChangeEventArgs.h"
#include "IFamily.h"
#include "IGenericElement.h"
#include "IImportCADElement.h"
#include "IInstanceType.h"
#include "IJournalCommandData.h"
#include "IModelView.h"
#include "ITransactionEvent.h"
#include "ITransactionEventArgs.h"
#include "IUiDocument.h"
#include "IUiDocumentEvent.h"
#include "IUiDocumentEventArgs.h"
#include "IUiDocumentViewManager.h"
#include "IUiManager.h"
#include "IUiView.h"
#include "IUiViewEvent.h"
#include "IUiViewEventArgs.h"
#include "IUndoRedoEvent.h"
#include "IUndoRedoEventArgs.h"
#include "IUserTransaction.h"
#include "IWorkPlane.h"
#include "InplaceEditModeBehavior.h"
#include "InplaceEditModelViewProjectData.h"
#include "InplaceEditSharedContent.h"
#include "JournalUtils.h"
#include "UiDocumentViewUtils.h"
#include "qnamespace.h"
#include "IFamilyExternalForm.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gfam;
using namespace gcmp;
using namespace gnuf;

constexpr wchar_t* defaultIcon = L":/image/ModelView";

namespace
{
    // 判断当前要创建的实例是否为轮廓族类型
    bool IsProfileFamily(const TreeNode* pCurrentTreeNode)
    {
        std::wstring familyName;
        if (pCurrentTreeNode)
        {
            TreeNode* pParent = pCurrentTreeNode->parentNode();
            if (pParent)
            {
                if (pParent->nodeInfo(0))
                {
                    familyName = pParent->nodeInfo(0)->caption();
                }
            }
        }

        IUiDocumentViewManager* pUiDocumentViewManager = IUiDocumentViewManager::Get();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pUiDocumentViewManager, L"pUiDocumentViewManager为空", L"paramodel", L"2024-02-20");
        IUiDocument* pCurrentUiDocument = pUiDocumentViewManager->GetCurrentUiDocument();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentUiDocument, L"pCurrentUiDocument为空", L"paramodel", L"2024-02-20");
        IDocument* pDoc = pCurrentUiDocument->GetDbDocument();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空", L"paramodel", L"2024-02-20");

        IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamily, L"pFamily为空", L"paramodel", L"2024-02-20");
        auto* basicInfo = pFamily->GetBasicInformation();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(basicInfo, L"basicInfo为空", L"paramodel", L"2024-02-20");
        if (basicInfo->GetCategoryUid() == BuiltInCategoryUniIdentities::BICU_PROFILE)
            return true;

        return false;
    }
}

GnufModelViewBoard::GnufModelViewBoard()
    : m_uiDocId(-1)
    , m_isNeedUpdate(false)
    , m_bShowFamilyManagementMenuItem(GnufModelViewConfiguration::ShowFamilyManagementMenuItem())
    , m_cmdIdCreateFamilyInstance(GnufModelViewConfiguration::GetCreateFamilyInstanceCommandId())
    , m_cmdIdRenameFamily(GnufModelViewConfiguration::GetRenameFamilyCommandId())
    , m_cmdIdEditFamily(GnufModelViewConfiguration::GetEditFamilyCommandId())
    , m_cmdIdLoadFamily(GnufModelViewConfiguration::GetLoadFamilyCommandId())
    , m_cmdIdLoadSubFamily(GnufModelViewConfiguration::GetLoadSubFamilyCommandId())
    , m_cmdIdSaveAsFamily(GnufModelViewConfiguration::GetSaveAsFamilyCommandId())
    , m_cmdIdRemoveFamily(GnufModelViewConfiguration::GetDeleteFamilyCommandId())
    , m_cmdIdRemoveImportedObject(GnufModelViewConfiguration::GetRemoveImportedObjectCommandId())
    , m_tree(nullptr)
{

}

void GnufModelViewBoard::Initialize(gnuf::TreeBoard* tree)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(tree, L"invalid tree", L"paramodel", L"2024-02-20");
    m_tree = tree;

    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr, L"invalid pUiDocViewMgr", L"paramodel", L"2024-02-20");

    IUiDocumentEvent* pUiDocEvent = pUiDocViewMgr->GetUiDocumentEvent();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocEvent, L"invalid pUiDocEvent", L"paramodel", L"2024-02-20");

    IUiViewEvent* pUiViewEvent = pUiDocViewMgr->GetUiViewEvent();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiViewEvent, L"invalid pUiViewEvent", L"paramodel", L"2024-02-20");

    pUiDocEvent->Add(this);
    pUiViewEvent->Add(this);
}

void GnufModelViewBoard::On(gcmp::IUiDocumentEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs, L"pArgs为空。", L"paramodel", L"2024-02-20");

    switch (pArgs->GetType())
    {
    case UiDocumentEventType::UiDocumentActivated:
    {
        IUiDocument* pUIDoc = pArgs->GetUiDocument();
        DBG_WARN_AND_BREAK_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空", L"paramodel", L"2024-02-20");

        m_uiDocId = pUIDoc->GetId();
        AttachEventHandler(pUIDoc);
        ExplorerBlockManager::getInstance()->initBlocks(m_tree);
        break;
    }

    case UiDocumentEventType::UiDocumentDeactivated:
    {
        IUiDocument* pUIDoc = pArgs->GetUiDocument();
        DBG_WARN_AND_BREAK_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空", L"paramodel", L"2024-02-20");

        if (m_uiDocId != pUIDoc->GetId()) break;
        DetachEventHandler(pUIDoc);
        m_uiDocId = -1;
        ExplorerBlockManager::getInstance()->destroyBlocks();
        break;
    }
    }
}

void GnufModelViewBoard::On(gcmp::IUiViewEventArgs* pArgs)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pArgs && pArgs->GetUiView(), L"pArgs为空或UiView为空。", L"paramodel", L"2024-02-20");

    if (UiViewEventType::UiViewActivated == pArgs->GetType())
    {
        if (pArgs->GetUiView())
        {
            IUiDocument* pUIDoc = pArgs->GetUiView()->GetUiDocument();
            m_uiDocId = pUIDoc->GetId();
            Refresh();
        }
    }
}

void GnufModelViewBoard::On(gcmp::IUndoRedoEventArgs* pArgs)
{
    if (!pArgs)
        return;

    UndoRedoEventType eventType = pArgs->GetType();
    switch (eventType)
    {
    case PostUndo:
    case PostRedo:
    {
        if (m_isNeedUpdate && m_tree && m_tree->isVisible())
        {
            Refresh();
        }
        break;
    }
    default:
        break;
    }
}

void GnufModelViewBoard::On(gcmp::ITransactionEventArgs* pArgs)
{
    if (!pArgs)
        return;

    TransactionEventType eventType = pArgs->GetType();
    switch (eventType)
    {
    case gcmp::PostCommit:
    case gcmp::PostRollBack:
    {
        if (m_isNeedUpdate && m_tree && m_tree->isVisible())
        {
            Refresh();
        }
        break;
    }
    default:
        break;
    }
}

void GnufModelViewBoard::On(gcmp::IElementsChangeEventArgs* pArgs)
{
    if (!pArgs)
        return;

    const std::vector<const IElement*> pElements = pArgs->GetElements();
    if (pElements.empty())
    {
        return;
    }

    IUiDocumentViewManager* pDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDocViewMgr, L"pDocViewMgr为空", L"paramodel", L"2024-02-20");
    IUiDocument* pUIDoc = pDocViewMgr->GetCurrentUiDocument();

    FOR_EACH(pElement, pElements)
    {
        if (pUIDoc && pUIDoc->GetDbDocument() == pElement->GetDocument())
        {
            if (const IModelView* pModelView = quick_cast<const IModelView>(pElement))
            {
                m_isNeedUpdate = true;
            }
            else if (const IFamily* pFamily = quick_cast<const IFamily>(pElement))
            {
                m_isNeedUpdate = true;
            }
            else if (const IInstanceType* pInstancetype = quick_cast<const IInstanceType>(pElement))
            {
                m_isNeedUpdate = true;
            }
            else if (const IImportCADElement* pImportedObject = quick_cast<const IImportCADElement>(pElement))
            {
                m_isNeedUpdate = true;
            }
            else if (pElement->GetBasicInformation()
                && pElement->GetBasicInformation()->GetCategoryUid() == gcmp::BuiltInCategoryUniIdentities::BICU_IMPORTED_SKP_OBJECT)
            {
                m_isNeedUpdate = true;
            }
            else if (const IWorkPlane* pWorkPlane = quick_cast<const IWorkPlane>(pElement))
            {
                m_isNeedUpdate = true;
            }
            else if(const IGenericElement* pGenericElement = quick_cast<const IGenericElement>(pElement))
            {
                if (const IFamilyExternalForm* pFamilyExternalForm = quick_cast<const IFamilyExternalForm>(pGenericElement->GetExternalObject()))
                {
                    m_isNeedUpdate = true;
                }
            }
        }
    }
}

void GnufModelViewBoard::On(gcmp::IDrawingViewportEventArgs* pArgs)
{
    if (pArgs == nullptr)
        return;

    IUiDocumentViewManager* pDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDocViewMgr, L"pDocViewMgr为空", L"paramodel", L"2024-02-20");
    IUiDocument *pUiDocument = pDocViewMgr->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocument, L"pUiDocument为空", L"paramodel", L"2024-02-20");
    IDocument* pDoc = pUiDocument->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空", L"paramodel", L"2024-02-20");
    if (pDoc != pArgs->GetDocument())
        return;
}

void GnufModelViewBoard::onTreeItemDbClicked(gnuf::TreeNode* item)
{
    if (item == nullptr)
        return;

    if (!item->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE).empty())
    {
        GnufFamilyTreeNodeUtil::EditFamilyTypeParameter(item);
    }
    else if (!item->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).empty()
        && !item->userDataAt(Gnuf_DETAILLIST_USER_DATA_ROLE).empty())
    {
        const gcmp::Any & data = item->userDataAt(Gnuf_DETAILLIST_USER_DATA_ROLE);
        Int64 viewId = data.cast<Int64>();
        ElementId modelViewId(viewId);

        notify(std::bind(&GnufModelViewBoardHandler::onDetailListItemDbClicked, std::placeholders::_1, std::cref(modelViewId)));
    }
    else
    {
        // 得到选中的ModelView。
        const gcmp::Any & data = item->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE);
        if (data.empty()) return;

        Int64 viewId = data.cast<Int64>();
        ElementId modelViewId(viewId);
        if (!modelViewId.IsValid())
            return;

        ActivateView(modelViewId);
        return;
    }
}

void gfam::GnufModelViewBoard::ActivateView(ElementId modelViewId)
{
    GetProjectModelViewData(modelViewId);

    DBG_WARN_AND_RETURN_VOID_UNLESS(IUiManager::Get() != nullptr, L"IUiManager::Get()不能为空", L"paramodel", L"2024-02-20");
    IApplicationWindow* pUIMainWnd = IUiManager::Get()->GetApplicationWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIMainWnd != nullptr, L"pUIMainWnd不能为空", L"paramodel", L"2024-02-20");
    IUiDocumentViewManager* pUiDocumentViewManager = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocumentViewManager, L"pUiDocumentViewManager为空", L"paramodel", L"2024-02-20");
    IUiDocument* pUIDoc = pUiDocumentViewManager->GetUiDocumentByRuntimeId(m_uiDocId);
    if (pUIDoc == nullptr)
        return;

    IDocument* pDbDoc = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空", L"paramodel", L"2024-02-20");

    IModelView* pModelView = quick_cast<IModelView>(pDbDoc->GetElement(modelViewId));
    if (pModelView == nullptr)
        return;

    std::wstring viewTag = L"";
    if (const ExplorerBlock* pBlock = ExplorerBlockManager::getInstance()->findSourceBlock(pModelView))
    {
        if (const DynamicExplorerBlock* pDynamicBlock = dynamic_cast<const DynamicExplorerBlock*>(pBlock))
        {
            viewTag = pDynamicBlock->getBlockName();
        }
    }

    if (gcmp::InplaceEditModelViewProjectData::Get(pModelView))
    {
        static int inplaceViewIndex = 0;
        std::wstringstream ssInplaceViewTag;
        ssInplaceViewTag << L"项目_" << inplaceViewIndex;
        viewTag = ssInplaceViewTag.str();
        inplaceViewIndex++;
    }

    IUiView* pView = gfam::UiDocUtils::CreateUiView(pUIDoc, modelViewId, viewTag, nullptr);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pView != nullptr, L"IUiView为空", L"paramodel", L"2024-02-20");

    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");
    pUiDocViewMgr->ActivateUiView(pView, false);

    if (IActionManager::CurrentAction() == nullptr)
    {
        //进入到默认工具
        ICommandManager* pCmdMgr = ICommandManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
        IUiView* pCurrentUiView = pUiDocViewMgr->GetCurrentUiView();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentUiView != nullptr, L"pCurrentUiView为空", L"paramodel", L"2024-02-20");
        pCmdMgr->SendCommand(pCurrentUiView->GetDefaultActionCommand());
    }
    HighlightSelectedModelView(pDbDoc, pView);
}

void GnufModelViewBoard::onTreeItemRButtonClicked(gnuf::TreeNode* item, int x, int y)
{
    if (item == nullptr) return;
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");

    if (FamilyCmdAvailibilityUtils::IsInProfileEditMode())
        return;

    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");
    IUiDocument* pUIDoc = pUiDocViewMgr->GetUiDocumentByRuntimeId(m_uiDocId);
    if (pUIDoc == nullptr) return;

    IDocument* pDbDoc = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空", L"paramodel", L"2024-02-20");

    if (pDbDoc->IsReadonlyForSharingViolation())
        return;

    m_contextMenu.reset();
    m_contextMenu = NEW_AS_OWNER_PTR(ContextMenu, gcmp::UniqueString::Find("ModelViewBoard/ContextMenu"));
    if (!m_contextMenu)
    {
        return;
    }
    gcmp::OwnerPtr< AppearanceSetting > setting = NEW_AS_OWNER_PTR(
        AppearanceSetting, AppearanceSetting::EStyle::eContextMenu);
    m_contextMenu->setEventHandler(this);
    m_contextMenu->setAppearanceSetting(TransferOwnership(setting));
    m_contextMenu->setWantToMarkTheSelected(true);
    m_contextMenu->setSupportMultiSelection(false);

    m_tree->setCurrentNode(item);
    item->setSelect(true);

    if (!item->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE).empty())
    {
        UpdateFamilyTreeItemContextMenu(item);
    }
    else if (!item->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).empty() && m_contextMenu->addEntry())
    {
        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"删除"));
    }
    else
    {
        return;
    }

    m_contextMenu->contents().empty() ? nullptr : m_contextMenu->popup(x, y);
}

bool GnufModelViewBoard::onKeyDown(gnuf::Item* item, int key, bool, bool, bool, bool)
{
    bool bRet = false;
    switch (key)
    {
    case Qt::Key_Delete:
        bRet = true;
        RemoveSelectedModelView();
        break;
    default:
        break;
    }

    return bRet;
}

void GnufModelViewBoard::onCurrentIndexChanged(gnuf::ContextMenu* menu)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(menu != nullptr, L"menu为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_contextMenu != nullptr, L"m_contextMenu为空", L"paramodel", L"2024-02-20");

    TreeNode* item = m_tree->currentNode();
    if (item == nullptr) return;

    int index = menu->currentIndex();

    if (!item->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE).empty())
    {
        FamilyTreeNodeType nodeType = item->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE).cast<FamilyTreeNodeType>();
        if (nodeType == FamilyTreeNodeType::TWNT_FAMILY)
        {
            if (true)
            {
                switch (index)
                {
                case 0: RenameFamily(); break;
                case 1: EditFamily(); break;
                case 2: SaveAsFamily(); break;
                case 3: RemoveFamily(); break;
                default: break;
                }
            }
            else
            {
                switch (index)
                {
                case 0: RenameFamily(); break;
                case 1: RemoveFamily(); break;
                default: break;
                }
            }
        }
        else if (nodeType == FamilyTreeNodeType::TWNT_FAMILYTYPE)
        {
            if(!CmdAvailibilityUtils::IsInEditMode() || CmdAvailibilityUtils::IsInInPlaceEditMode())
            {
                if (m_contextMenu->addEntry())
                {
                    m_contextMenu->addEntry()->setCaption(GBMP_TR(L"创建实例"));
                }

                switch (index)
                {
                case 0: CreateFamilyInstance(); break;
                default: break;
                }
            }
        }
        else if (nodeType == FamilyTreeNodeType::TWNT_FAMILY_ROOT)
        {
            if(true)
            {
                bool hasLoadSubFamilyMenu = m_bShowFamilyManagementMenuItem;
                switch (index)
                {
                case 0: m_bShowFamilyManagementMenuItem ? LoadFamily() : item->setExpanded(false); break;
                case 1: hasLoadSubFamilyMenu ? LoadSubFamily() : SetAllItemsExpandedStatus(item, false); break;
                case 2: hasLoadSubFamilyMenu ? SetAllItemsExpandedStatus(item, false) : SetAllItemsExpandedStatus(item, true); break;
                case 3: hasLoadSubFamilyMenu ? SetAllItemsExpandedStatus(item, true) : nullptr; break;
                default: break;
                }
            }
            else
            {
                switch (index)
                {
                case 0: m_bShowFamilyManagementMenuItem ? item->setExpanded(false) : item->setExpanded(true); break;
                case 1: m_bShowFamilyManagementMenuItem ? item->setExpanded(true) : nullptr; break;
                default: break;
                }
            }
        }
        else if (nodeType == FamilyTreeNodeType::TWNT_IMPORTED_OBJECT_ROOT)
        {
            switch (index)
            {
            case 0: item->setExpanded(false); break;
            case 1: item->setExpanded(true); break;
            default: break;
            }
        }

        else if (nodeType == FamilyTreeNodeType::TWNT_CAD_SHEET)
        {
            switch (index)
            {
            case 0: RemoveImportedObject(); break;
            default: break;
            }
        }
    }
    else if (!item->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).empty())
    {
        switch (index)
        {
        case 0: RemoveSelectedModelView(); break;
        default: break;
        }
    }
}

void GnufModelViewBoard::UpdateFamilyTreeItemContextMenu(TreeNode* selectedItem)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(selectedItem != nullptr, L"selectedItem为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_contextMenu != nullptr, L"m_contextMenu为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_contextMenu->addEntry() != nullptr, L"m_contextMenu->addEntry()为空", L"paramodel", L"2024-02-20");

    // 单选
    FamilyTreeNodeType nodeType = selectedItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE).cast<FamilyTreeNodeType>();
    if (nodeType == FamilyTreeNodeType::TWNT_FAMILY)
    {
        if (m_bShowFamilyManagementMenuItem)
        {
            m_contextMenu->addEntry()->setCaption(GBMP_TR(L"重命名"));
            if(true)
            {
                if (!m_cmdIdEditFamily.empty())
                {
                    m_contextMenu->addEntry()->setCaption(GBMP_TR(L"编辑"));
                }

                m_contextMenu->addEntry()->setCaption(GBMP_TR(L"另存为..."));
            }
            m_contextMenu->addEntry()->setCaption(GBMP_TR(L"删除"));
        }
    }
    else if (nodeType == FamilyTreeNodeType::TWNT_FAMILYTYPE)
    {
        if (!CmdAvailibilityUtils::IsInEditMode() || CmdAvailibilityUtils::IsInInPlaceEditMode())
        {
            // 过滤轮廓族，禁止轮廓族在左侧导航栏创建实例
            if (IsProfileFamily(m_tree->currentNode()))
                return;

            m_contextMenu->addEntry()->setCaption(GBMP_TR(L"创建实例"));
        }
    }
    else if (nodeType == FamilyTreeNodeType::TWNT_FAMILY_ROOT)
    {
        if (m_bShowFamilyManagementMenuItem)
        {
            {
                m_contextMenu->addEntry()->setCaption(GBMP_TR(L"载入..."));
            }
        }

        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"全部折叠..."));

        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"全部展开..."));
    }
    else if (nodeType == FamilyTreeNodeType::TWNT_IMPORTED_OBJECT_ROOT)
    {
        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"全部折叠..."));

        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"全部展开..."));
    }

    else if (nodeType == FamilyTreeNodeType::TWNT_CAD_SHEET)
    {
        m_contextMenu->addEntry()->setCaption(GBMP_TR(L"删除"));
    }
}

void GnufModelViewBoard::CreateFamilyInstance()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdCreateFamilyInstance.empty(), L"CreateFamilyInstance命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::CreateFamilyInstance(m_tree->currentNode(), m_cmdIdCreateFamilyInstance);
}

void GnufModelViewBoard::RenameFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdRenameFamily.empty(), L"RenameFamily命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::RenameFamily(m_tree->currentNode(), m_cmdIdRenameFamily);
}

void GnufModelViewBoard::EditFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdEditFamily.empty(), L"EditFamily命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::EditFamily(m_tree->currentNode(), m_cmdIdEditFamily);
}

void GnufModelViewBoard::SaveAsFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdSaveAsFamily.empty(), L"SaveAsFamily命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::SaveFamilyAs(m_tree->currentNode(), m_cmdIdSaveAsFamily);
}

void GnufModelViewBoard::LoadFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdLoadFamily.empty(), L"LoadFamily命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::LoadFamily(m_tree->currentNode(), m_cmdIdLoadFamily);
}

void GnufModelViewBoard::LoadSubFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdLoadFamily.empty(), L"LoadFamily命令为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree, L"m_tree为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::LoadFamily(m_tree->currentNode(), m_cmdIdLoadSubFamily);
}

void GnufModelViewBoard::RemoveFamily()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdRemoveFamily.empty(), L"RemoveFamily命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::RemoveSelectedFamlies(std::list<TreeNode*>(1, m_tree->currentNode()), m_cmdIdRemoveFamily);
}

void gfam::GnufModelViewBoard::RemoveImportedObject()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree, L"m_tree为空指针", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_cmdIdRemoveImportedObject.empty(), L"RemoveImportedObject命令为空", L"paramodel", L"2024-02-20");

    GnufFamilyTreeNodeUtil::RemoveImportedObject(m_tree->currentNode(), m_cmdIdRemoveImportedObject);
}

void GnufModelViewBoard::Refresh()
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");

    IUiDocument* pUiDoc = pUiDocViewMgr->GetUiDocumentByRuntimeId(m_uiDocId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc != nullptr, L"pUiDoc为空", L"paramodel", L"2024-02-20");

    ExplorerBlockManager::getInstance()->refresh(pUiDoc);

    //重置更新标记
    m_isNeedUpdate = false;

    // 设置当前视图为选中状态
    HighlightSelectedModelView(pUiDoc->GetDbDocument(), pUiDocViewMgr->GetCurrentUiView());
}

const gcmp::IModelView* GnufModelViewBoard::GetCurModelView()
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");

    IUiDocument* pUiDoc = pUiDocViewMgr->GetUiDocumentByRuntimeId(m_uiDocId);

    std::wstring errorMessage = L"";
    const gcmp::IDrawingLayoutManager* pDrawingLayoutMgr = gcmp::IDrawingLayoutManager::Get(pUiDoc->GetDbDocument(), &errorMessage);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDrawingLayoutMgr != nullptr, errorMessage, L"paramodel", L"2024-02-20");
    std::vector<gcmp::IDrawingLayout*> cDrawingLayout = pDrawingLayoutMgr->GetAllLayouts();

    for (int i = 0; i < cDrawingLayout.size(); ++i)
    {
        const gcmp::IDrawingLayout* pTemDrawSingle = cDrawingLayout[i];
        std::vector<gcmp::IDrawingViewport*> cAllViewPort = pTemDrawSingle->GetAllViewports();
        for (int j = 0; j < cAllViewPort.size(); ++j)
        {
            if (cAllViewPort[j]->IsActive())
            {
                return pTemDrawSingle->GetModelView();
            }
        }
    }

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocViewMgr->GetCurrentUiView() != nullptr, L"pUiDocViewMgr->GetCurrentUiView()为空", L"paramodel", L"2024-02-20");

    return pUiDocViewMgr->GetCurrentUiView()->GetModelView();
}

bool GnufModelViewBoard::GetSelectedViewPort(gcmp::IDocument* pDoc, gcmp::ElementId& selectedId)
{
    std::wstring errorMessage = L"";
    const gcmp::IDrawingLayoutManager* pDrawingLayoutMgr = gcmp::IDrawingLayoutManager::Get(pDoc, &errorMessage);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDrawingLayoutMgr != nullptr, errorMessage, L"paramodel", L"2024-02-20");
    std::vector<gcmp::IDrawingLayout*> cDrawingLayout = pDrawingLayoutMgr->GetAllLayouts();
    for (int i = 0; i < cDrawingLayout.size(); ++i)
    {
        const gcmp::IDrawingLayout* pTemDrawSingle = cDrawingLayout[i];
        std::vector<gcmp::IDrawingViewport*> cAllViewPort = pTemDrawSingle->GetAllViewports();
        for (int j = 0; j < cAllViewPort.size(); ++j)
        {
            if (cAllViewPort[j]->IsActive())
            {
                const gcmp::IElement* viewPortElement = cAllViewPort[j]->GetOwnerElement();
                selectedId = viewPortElement->GetElementId();
                return true;
            }
        }
    }

    return false;
}

void GnufModelViewBoard::HighlightSelectedModelView(gcmp::IDocument* pDoc, const IUiView* pUIView)
{
    if (!pUIView)
        return;

    // 视图名称。
    const gcmp::IModelView * pModelView = GetCurModelView();
    if (nullptr == pModelView)
        return;

    // 视图名称。
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView->GetBasicInformation() != nullptr, L"pModelView->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
    const std::wstring viewName = pModelView->GetBasicInformation()->GetName();
    gcmp::ElementId selectViewPortId;
    GetSelectedViewPort(pDoc, selectViewPortId);

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");
    for (TreeNode* viewTypeItem : m_tree->rawTrees())
    {
        viewTypeItem->setSelect(false);
        for (TreeNode* viewItem : viewTypeItem->rawSubNodes())
        {
            if (!viewItem->nodeInfo(0))
            {
                continue;
            }

            std::wstring viewText = viewItem->nodeInfo(0)->caption();
            if (viewItem->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).empty()) continue;

            Int64 viewId = viewItem->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).cast<Int64>();
            if ((viewText == viewName && pModelView->GetBasicInformation()->GetElementId().AsInt64() == viewId) ||
                (selectViewPortId.IsValid() && selectViewPortId.AsInt64() == viewId))
            {
                viewItem->setActive(true);
                viewItem->setSelect(true);
            }
            else
            {
                viewItem->setActive(false);
                viewItem->setSelect(false);
            }
        }
    }
}

void GnufModelViewBoard::RemoveSelectedModelView()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_tree != nullptr, L"m_tree为空", L"paramodel", L"2024-02-20");

    TreeNode* pViewItem = m_tree->currentNode();
    if (pViewItem != nullptr)
    {
        const gcmp::Any & data = pViewItem->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE);
        if (data.empty()) return;

        Int64 viewId = data.cast<Int64>();

        IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");
        IUiDocument* pUIDoc = pUiDocViewMgr->GetCurrentUiDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空", L"paramodel", L"2024-02-20");
        IDocument* pDoc = pUIDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"pDoc不能为空", L"paramodel", L"2024-02-20");

        ElementId modelviewId(viewId);
        IModelView* pModelView = dynamic_cast<IModelView*>(pDoc->GetElement(modelviewId));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView != nullptr, L"找不到要删除的视图", L"paramodel", L"2024-02-20");

        CommandParameters cmdParams;
        SetModelViewCommandParameters(pModelView, cmdParams);

        OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
        DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
        opJournalCmdData->SetCommandName(ID_CMD_REMOVE_SELECTED_MODEL_VIEW_FAMILY);
        opJournalCmdData->SetParameterArray(cmdParams);
        JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

        ICommandManager* pCmdMgr = ICommandManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
        pCmdMgr->SendCommand(ID_CMD_REMOVE_SELECTED_MODEL_VIEW_FAMILY, cmdParams);
    }
}

void gfam::GnufModelViewBoard::GetProjectModelViewData(const gcmp::ElementId & modelViewId)
{
    IDocument *pDbDoc = UiDocumentViewUtils::GetCurrentDocument();;
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDbDoc != nullptr, L"pDbDoc为空", L"paramodel", L"2024-02-20");

    IModelView* pModelView = quick_cast<IModelView>(pDbDoc->GetElement(modelViewId));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView不能为空", L"paramodel", L"2024-02-20");

    if (!gcmp::InplaceEditModelViewProjectData::Get(pModelView)) // 非项目视图
    {
        return;
    }

    const InplaceEditModelViewProjectData* pProjectViewData = InplaceEditModelViewProjectData::Get(pModelView);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pProjectViewData, L"激活的应该是项目视图", L"paramodel", L"2024-02-20");

    // 检查是否已存在项目视图数据，如果不存在，则需要请求项目视图数据
    if (!pProjectViewData->GetIsRequestingData() && !pProjectViewData->GetIsRequestedData())
    {
        // 获取项目端口
        const InplaceEditModeBehavior* pInplaceEdit = InplaceEditModeBehavior::Get(pDbDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInplaceEdit != nullptr, L"pInplaceEdit为空", L"paramodel", L"2024-02-20");
        uint16_t projectAppPort = pInplaceEdit->GetProjectAppPort();
        DBG_WARN_AND_RETURN_VOID_UNLESS(projectAppPort != 0, L"项目端口为空", L"paramodel", L"2024-02-20");

        OwnerPtr<IUserTransaction> opUt = IUserTransaction::Create(pDbDoc, GBMP_TR(L"修改项目视图数据状态"));
        DBG_WARN_AND_RETURN_VOID_UNLESS(opUt, L"opUt为空", L"paramodel", L"2024-02-20");

        InplaceEditModelViewProjectData* pProjectViewDataFw = InplaceEditModelViewProjectData::GetFw(pModelView);
        pProjectViewDataFw->SetIsRequestingData(true);
#pragma warning(push)
#pragma warning(disable: 4996)
        InplaceEditSharedModelViewInfo viewInfo(pModelView->GetUserDataId(), pModelView->GetName(), pModelView->GetViewType());
#pragma warning(pop)
        CommunicationProtocolUtils::SendIpcMessage(projectAppPort, FunctionType::InPlaceEdit, OperationType::RequestViewData, &viewInfo);
        opUt->Commit();
    }
}

void GnufModelViewBoard::AttachEventHandler(gcmp::IUiDocument* pUIDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空", L"paramodel", L"2024-02-20");
    if (pUIDoc)
    {
        IDocument* pDoc = pUIDoc->GetDbDocument();
        if (pDoc)
        {
            pDoc->AddElementsChangeEventHandler(ElementsChangeEventType::ElementsAdditionEvent, this);
            pDoc->AddElementsChangeEventHandler(ElementsChangeEventType::ElementsPreDeletionEvent, this);
            pDoc->AddElementsChangeEventHandler(ElementsChangeEventType::ElementsPostUpdationEvent, this);

            IUndoRedoEvent* pUndoRedoEvent = pDoc->GetUndoRedoEvent();
            pUndoRedoEvent->Add(this);

            ITransactionEvent* pTransactionEvent = pDoc->GetTransactionEvent();
            pTransactionEvent->Add(this);

            DBG_WARN_AND_RETURN_VOID_UNLESS(IDrawingLayout::GetViewportEvent() != nullptr, L"IDrawingLayout::GetViewportEvent()为空", L"paramodel", L"2024-02-20");
            IDrawingLayout::GetViewportEvent()->Add(this);
        }
    }

}

void GnufModelViewBoard::DetachEventHandler(gcmp::IUiDocument* pUIDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc != nullptr, L"pUIDoc不能为空", L"paramodel", L"2024-02-20");
    if (pUIDoc)
    {
        IDocument* pDoc = pUIDoc->GetDbDocument();
        if (pDoc)
        {
            pDoc->DeleteElementsChangeEventHandler(ElementsChangeEventType::ElementsAdditionEvent, this);
            pDoc->DeleteElementsChangeEventHandler(ElementsChangeEventType::ElementsPreDeletionEvent, this);
            pDoc->DeleteElementsChangeEventHandler(ElementsChangeEventType::ElementsPostUpdationEvent, this);

            IUndoRedoEvent* pUndoRedoEvent = pDoc->GetUndoRedoEvent();
            pUndoRedoEvent->Delete(this);

            ITransactionEvent* pTransactionEvent = pDoc->GetTransactionEvent();

            pTransactionEvent->Delete(this);

            DBG_WARN_AND_RETURN_VOID_UNLESS(IDrawingLayout::GetViewportEvent() != nullptr, L"IDrawingLayout::GetViewportEvent()为空", L"paramodel", L"2024-02-20");
            IDrawingLayout::GetViewportEvent()->Delete(this);
        }
    }
}

bool gfam::GnufModelViewBoard::onDragOff(TreeNode* node)
{
    if (nullptr == DragMove::current())
    {
        auto dm = DragMove::make(node, DragMove::eArrangementAreaContent);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(dm.ReleaseOwnership() != nullptr, L"dm.ReleaseOwnership()为空", L"paramodel", L"2024-02-20");
        dm.ReleaseOwnership()->setOwnerless();
    }

    return true;
}

void gfam::GnufModelViewBoard::onDrop(gnuf::TreeNode* pNode)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pNode, L"pNode is nullptr", L"paramodel", L"2024-02-20");

    gcmp::CommandParameters cmdParameters;
    cmdParameters[L"ViewId"] = pNode->userDataAt(Gnuf_MODEL_VIEW_USER_DATA_ROLE).cast<Int64>();
    ICommandManager* pCmdMgr = ICommandManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
    pCmdMgr->SendCommand(ID_CMD_GAP_CREATE_VIEWPORT, cmdParameters);
}

void gfam::GnufModelViewBoard::SetAllItemsExpandedStatus(gnuf::TreeNode * pParentItem, bool expandStatus)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParentItem, L"pParentItem指针为空", L"paramodel", L"2024-02-20");

    pParentItem->setExpanded(expandStatus);

    std::vector<TreeNode *> children = pParentItem->rawSubNodes();

    Int64  childCount = children.size();

    if (0 == childCount)
        return;

    for (auto item : children)
    {
        SetAllItemsExpandedStatus(item, expandStatus);
    }
}

void gfam::GnufModelViewBoard::SetModelViewCommandParameters(gcmp::IModelView* pModelView,gcmp::CommandParameters &cmdParams)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView->GetBasicInformation() != nullptr, L"pModelView->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
    std::wstring modelViewName = pModelView->GetBasicInformation()->GetName();
#pragma warning (push)
#pragma warning (disable: 4996)
    std::wstring modelViewType = pModelView->GetUserDataId();
#pragma warning (pop)

    cmdParams.emplace(L"ModelViewName", modelViewName);
    cmdParams.emplace(L"ModelViewType", modelViewType);
}
